package com.ht.aems.eas;

import com.ht.aems.fesmodel.data.MeasurePoint;
import rtdb.pas.AvcFesPoints;
import rtdb.pas.OpfFesPoints;

import java.util.Calendar;
import java.util.Date;

/**
 * Created by IntelliJ IDEA.
 * User: Dong Shufeng
 * Date: 11-9-7
 */
public class OpfPointsFiller {

    public static void updateOpfPoints(OpfFesPoints opfFesPoints, long endTime, long elapseTime, double pLossBefore, double pLossAfter, boolean converged) {
        if (opfFesPoints.dayCount == null) ;
        else if (setMeasureTime(endTime, opfFesPoints.dayCount))
            opfFesPoints.dayCount.setEngValue(1);
        else
            opfFesPoints.dayCount.setEngValue(opfFesPoints.dayCount.getEngValue() + 1);

        if (opfFesPoints.monthCount == null) ;
        else if (setMeasureTime(endTime, opfFesPoints.monthCount))
            opfFesPoints.monthCount.setEngValue(1);
        else
            opfFesPoints.monthCount.setEngValue(opfFesPoints.monthCount.getEngValue() + 1);

        if (opfFesPoints.yearCount == null) ;
        else if (setMeasureTime(endTime, opfFesPoints.yearCount))
            opfFesPoints.yearCount.setEngValue(1);
        else
            opfFesPoints.yearCount.setEngValue(opfFesPoints.yearCount.getEngValue() + 1);

        if (opfFesPoints.dayConvergeRate == null || opfFesPoints.dayCount == null) ;
        else if (setMeasureTime(endTime, opfFesPoints.dayConvergeRate))
            opfFesPoints.dayConvergeRate.setEngValue(converged ? 1.0 : 0.0);
        else
            opfFesPoints.dayConvergeRate.setEngValue(((converged ? 1.0 : 0.0) + opfFesPoints.dayConvergeRate.getEngValue() * opfFesPoints.dayCount.getEngValue()) / (1.0 + opfFesPoints.dayCount.getEngValue()));

        if (opfFesPoints.monthConvergeRate == null || opfFesPoints.monthCount == null) ;
        else if (setMeasureTime(endTime, opfFesPoints.monthConvergeRate))
            opfFesPoints.monthConvergeRate.setEngValue(converged ? 1.0 : 0.0);
        else
            opfFesPoints.monthConvergeRate.setEngValue(((converged ? 1.0 : 0.0) + opfFesPoints.monthConvergeRate.getEngValue() * opfFesPoints.monthCount.getEngValue()) / (1.0 + opfFesPoints.monthCount.getEngValue()));

        if (opfFesPoints.yearConvergeRate == null || opfFesPoints.yearCount == null) ;
        else if (setMeasureTime(endTime, opfFesPoints.yearConvergeRate))
            opfFesPoints.yearConvergeRate.setEngValue(converged ? 1.0 : 0.0);
        else
            opfFesPoints.yearConvergeRate.setEngValue(((converged ? 1.0 : 0.0) + opfFesPoints.yearConvergeRate.getEngValue() * opfFesPoints.yearCount.getEngValue()) / (1.0 + opfFesPoints.yearCount.getEngValue()));

        if (opfFesPoints.dayAvailableRate != null && opfFesPoints.dayConvergeRate != null) {
            opfFesPoints.dayAvailableRate.setTimestamp(new Date(endTime));
            opfFesPoints.dayAvailableRate.setEngValue(opfFesPoints.dayConvergeRate.getEngValue());
        }
        if (opfFesPoints.monthAvailableRate != null && opfFesPoints.monthConvergeRate != null) {
            opfFesPoints.monthAvailableRate.setTimestamp(new Date(endTime));
            opfFesPoints.monthAvailableRate.setEngValue(opfFesPoints.monthConvergeRate.getEngValue());
        }
        if (opfFesPoints.yearAvailableRate != null && opfFesPoints.yearConvergeRate != null) {
            opfFesPoints.yearAvailableRate.setTimestamp(new Date(endTime));
            opfFesPoints.yearAvailableRate.setEngValue(opfFesPoints.yearConvergeRate.getEngValue());
        }
        //current
        if (opfFesPoints.elapsedTime != null) {
            opfFesPoints.elapsedTime.setTimestamp(new Date(endTime));
            opfFesPoints.elapsedTime.setEngValue(elapseTime);
        }
        if (opfFesPoints.pLossBefore != null)
            opfFesPoints.pLossBefore.setEngValue(pLossBefore);
        if (opfFesPoints.pLossAfter != null)
            opfFesPoints.pLossAfter.setEngValue(pLossAfter);
    }

    /**
     * @param seTime end time state estimation
     * @param p      the measurement point to be set
     * @return if the value of the measurement should be reset
     */
    private static boolean setMeasureTime(long seTime, MeasurePoint p) {
        if (p.getTimestamp() == null) {
            p.setTimestamp(new Date(seTime));
            return true;
        }
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(seTime);
        Calendar pointTime = Calendar.getInstance();
        pointTime.setTime(p.getTimestamp());
        int rtType = p.getMeasureType();
        boolean result = false;
        switch (rtType) {
            case MeasurePoint.DAY:
                if (pointTime.get(Calendar.YEAR) != c.get(Calendar.YEAR) ||
                        pointTime.get(Calendar.DAY_OF_YEAR) != c.get(Calendar.DAY_OF_YEAR))
                    result = true;
            case MeasurePoint.MONTH:
                if (pointTime.get(Calendar.YEAR) != c.get(Calendar.YEAR) ||
                        pointTime.get(Calendar.MONTH) != c.get(Calendar.MONTH))
                    result = true;
            case MeasurePoint.YEAR:
                if (pointTime.get(Calendar.YEAR) != c.get(Calendar.YEAR))
                    result = true;
            default:
                break;
        }
        p.setTimestamp(new Date(seTime));
        return result;
    }
}
